package com.ly.im.netty;

import com.alibaba.fastjson.JSON;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;

public class WebSocketHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    private final Logger logger = LoggerFactory.getLogger(WebSocketHandler.class);

    public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    public static Map<String, Channel> cmap = new ConcurrentHashMap<>();

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        logger.info("与客户端建立连接，通道开启！");
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        logger.info("与客户端断开连接，通道关闭！");
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        //接收的消息
        Map map = JSON.parseObject(msg.text(), Map.class);
        logger.info("入参：{}", map);
        String type = map.get("type").toString();
        switch (type){
            case "1":   // 登录
                websocketLogin(map,ctx);
                break;
            case "2": // 发送对话消息
                send(map);
                break;
            case "3":   // 请求进行视频通话
                call(map);
                break;
            case "4":   // 对方回应通话
                response(map);
                break;
            case "5":   //传递请求off
                askoff(map);
                break;
            case "6":   //获取off
                getoff(map);
                break;
            case "7":
                answer(map);
                break;
            case "8":
                candidate(map);
                break;
        }
//        logger.info(String.format("收到客户端%s的数据：%s", ctx.channel().id(), msg.text()));
//        channelGroup.writeAndFlush(new TextWebSocketFrame("aaabbb"));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        // 异常处理
        logger.error("WebSocketHandler.exceptionCaught|异常:{}", cause.getMessage());
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        // 一但连接，第一个被执行
        logger.info("WebSocketHandler.handlerAdded|{}连接", ctx.channel().id().asLongText());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        // 移除通道及关联用户
        logger.info("WebSocketHandler.handlerRemoved|{}连接", ctx.channel().id().asLongText());
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        // 心跳检测相关方法 - 会主动调用handlerRemoved
        logger.info("WebSocketHandler.userEventTriggered|{}连接", ctx.channel().id().asLongText());
        if (evt instanceof IdleStateEvent){

        }else {
            super.userEventTriggered(ctx, evt);
        }
    }

    private void answer(Map map) {
        String to = map.get("to").toString();
        if (isLogin("user"+to)){
            Channel channel = getChannelByUid("user" + to);
            Map<String,Object> obj = new HashMap<>();
            obj.put("type",7); // 回应通话
            obj.put("uuid", UUID.randomUUID().toString());
            obj.put("from",map.get("uid").toString());
            obj.put("message",map.get("message"));
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(obj)));
        }else {
            logger.info("未登录");
        }
    }

    private void candidate(Map map) {
        String to = map.get("to").toString();
        if (isLogin("user"+to)){
            Channel channel = getChannelByUid("user" + to);
            Map<String,Object> obj = new HashMap<>();
            obj.put("type",8); // 回应通话
            obj.put("uuid", UUID.randomUUID().toString());
            obj.put("from",map.get("uid").toString());
            obj.put("message",map.get("message"));
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(obj)));
        }else {
            logger.info("未登录");
        }
    }

    private void getoff(Map map) {
        String to = map.get("to").toString();
        if (isLogin("user"+to)){
            Channel channel = getChannelByUid("user" + to);
            Map<String,Object> obj = new HashMap<>();
            obj.put("type",6); // 回应通话
            obj.put("uuid", UUID.randomUUID().toString());
            obj.put("from",map.get("uid").toString());
            obj.put("message",map.get("message"));
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(obj)));
        }else {
            logger.info("未登录");
        }
    }

    private void askoff(Map map) {
        String to = map.get("to").toString();
        if (isLogin("user"+to)){
            Channel channel = getChannelByUid("user" + to);
            Map<String,Object> obj = new HashMap<>();
            obj.put("type",5); // 回应通话
            obj.put("uuid", UUID.randomUUID().toString());
            obj.put("from",map.get("uid").toString());
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(obj)));
        }else {
            logger.info("未登录");
        }
    }

    private void response(Map map) {
        String to = map.get("to").toString();
        if (isLogin("user"+to)){
            Channel channel = getChannelByUid("user" + to);
            Map<String,Object> obj = new HashMap<>();
            obj.put("type",4); // 回应通话
            obj.put("uuid", UUID.randomUUID().toString());
            obj.put("from",map.get("uid").toString());
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(obj)));
        }else {
            logger.info("未登录");
        }
    }

    private void call(Map map) {
        String to = map.get("to").toString();
        if (isLogin("user"+to)){
            Channel channel = getChannelByUid("user" + to);
            Map<String,Object> obj = new HashMap<>();
            obj.put("type",3); // 对话
            obj.put("uuid", UUID.randomUUID().toString());
            obj.put("from",map.get("uid").toString());
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(obj)));
        }else {
            logger.info("未登录");
        }
    }

    private void send(Map map) {
        String to = map.get("to").toString();
        logger.info("当前在线用户:{}", cmap);
        if (isLogin("user"+to)){
            Channel channel = getChannelByUid("user" + to);
            Map<String,Object> obj = new HashMap<>();
            obj.put("type",2); // 对话
            obj.put("uuid", UUID.randomUUID().toString());
            channel.writeAndFlush(new TextWebSocketFrame(JSON.toJSONString(obj)));
        }else {
            logger.info("未登录");
        }
    }

    private void websocketLogin(Map map,ChannelHandlerContext ctx) {
        String uid = map.get("uid").toString();
        logger.info("当前已登录用户1:{}", cmap);
        putUser("user"+uid, ctx.channel());
        logger.info("当前已登录用户2:{}", cmap);
    }

    private void sendMessage(ChannelHandlerContext ctx) throws InterruptedException {
        String message = "我是服务器，你好呀";
        ctx.writeAndFlush(new TextWebSocketFrame("hello"));
    }

    public void putUser(String key, Channel channel){
        // 保存登录用户信息
        cmap.put(key, channel);
    }

    public Channel getChannelByUid(String uid){
        // 获取对应用户channel
        return cmap.get(uid);
    }

    public boolean isLogin(String uid){
        // 校验用户是否存在
        return cmap.containsKey(uid);
    }

}